package com.metadata_system.system.service;

import com.metadata_system.common.db.entity.MetadataView;
import com.metadata_system.common.db.entity.User;
import com.metadata_system.common.db.entity.UserOperationLog;
import com.metadata_system.common.db.mapper.*;
import com.metadata_system.common.dto.ApiResult;
import com.metadata_system.common.service.UserOperationLogService;
import com.metadata_system.system.request.MetadataViewListParams;
import com.metadata_system.system.response.ViewItem;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class MetadataViewService {
    @Autowired(required = false)
    private MetadataViewMapper metadataViewMapper;
    @Autowired(required = false)
    private MetadataNodeMapper metadataNodeMapper;
    @Autowired(required = false)
    private MetadataEdgeMapper metadataEdgeMapper;

    @Autowired
    private MetadataService metadataService;

    /**
     * 获取元数据视图列表
     *
     * @param listParams
     * @return
     */
    public ApiResult getList(MetadataViewListParams listParams) {
        Example example = new Example(MetadataView.class);
        Example.Criteria criteria = example.createCriteria();
        if (listParams.getMetadataId() != null) {
            criteria.andEqualTo("metadataId", listParams.getMetadataId());
        }
        if (!StringUtils.isBlank(listParams.getName())) {
            criteria.andLike("name", "%" + listParams.getName() + "%");
        }
        listParams.setOrder(example, "id,updatedTime,createdTime");
        int total = this.metadataViewMapper.selectCountByExample(example);
        List<MetadataView> list = new ArrayList<>();
        if (total > 0) {
            list = this.metadataViewMapper.selectByExampleAndRowBounds(example, listParams.getRowRunds());
        }
        return ApiResult.successPage(list, total);
    }

    /**
     * 获取元数据视图详情
     *
     * @param id
     * @return
     */
    public ApiResult getDetail(Integer id) {
        MetadataView metadataView = this.metadataViewMapper.selectByPrimaryKey(id);
        return ApiResult.success(metadataView);
    }

    /**
     * 新增-元数据视图
     *
     * @param metadataView
     * @return
     */
    public ApiResult create(MetadataView metadataView, Integer userId) {
        // 校验参数
        if (StringUtils.isBlank(metadataView.getName())) {
            return ApiResult.error("名称不能为空");
        }
        if (metadataView.getName().length() < 2 || metadataView.getName().length() > 30) {
            return ApiResult.error("名称长度必须在2-30个字符之间");
        }
        if (StringUtils.isBlank(metadataView.getShortName())) {
            metadataView.setShortName(metadataView.getName().substring(0, 2));
        }
        if (metadataView.getShortName().isEmpty() || metadataView.getShortName().length() > 5) {
            return ApiResult.error("简称长度必须在1-5个字符之间");
        }
        // 校验名称是否重复
        Example example = new Example(MetadataView.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("name", metadataView.getName());
        int i = this.metadataViewMapper.selectCountByExample(example);
        if (i > 0) {
            return ApiResult.error("名称重复");
        }
        // 校验元数据是否存在
        if (metadataView.getMetadataId() == null) {
            return ApiResult.error("元数据ID 不能为空");
        }
        metadataView.setNodeTotal(0);
        metadataView.setEdgeTotal(0);
        metadataView.setConfig("{}");
        metadataView.setCreatedTime(new Date());
        metadataView.setUpdatedTime(metadataView.getCreatedTime());
        this.metadataViewMapper.insertSelective(metadataView);
        Integer lastInsetId = this.metadataViewMapper.getLastInsertId();

        // 更新元数据视图数量
        this.metadataService.updateView(metadataView.getMetadataId(), userId);

        // 增加操作日志
        this.userOperationLogService.insert(UserOperationLog.builder()
                .userId(userId)
                .username(userMapper.selectByPrimaryKey(userId).getUsername())
                .type("MetadataView.Create")
                .content("新增视图: " + metadataView.getName())
                .params(lastInsetId.toString())
                .createdTime(new Date())
                .build());

        return ApiResult.success(ViewItem.builder()
                .id(lastInsetId)
                .name(metadataView.getName())
                .shortName(metadataView.getShortName())
                .build());
    }

    public ApiResult update(MetadataView metadataView, Integer userId) {
        MetadataView currMetadataView = this.metadataViewMapper.selectByPrimaryKey(metadataView.getId());
        if (currMetadataView == null) {
            return ApiResult.error("视图不存在");
        }
        MetadataView updateMetadataView = MetadataView.builder().id(metadataView.getId()).build();
        // 校验参数
        if (metadataView.getName() != null) {
            if (StringUtils.isBlank(metadataView.getName())) {
                return ApiResult.error("名称不能为空");
            }
            if (metadataView.getName().length() < 2 || metadataView.getName().length() > 30) {
                return ApiResult.error("名称长度必须在2-30个字符之间");
            }
            updateMetadataView.setName(metadataView.getName());
        }
        if (metadataView.getShortName() != null) {
            if (metadataView.getShortName().isEmpty() || metadataView.getShortName().length() > 5) {
                return ApiResult.error("简称长度必须在1-5个字符之间");
            }
            updateMetadataView.setShortName(metadataView.getShortName());
        }
        if (metadataView.getConfig() != null) {
            updateMetadataView.setConfig(metadataView.getConfig());
        }
        if (updateMetadataView.getName() != null) {
            if (updateMetadataView.getName().length() < 2 || updateMetadataView.getName().length() > 30) {
                return ApiResult.error("名称长度必须在2-30个字符之间");
            }
            updateMetadataView.setName(metadataView.getName());
        }
        updateMetadataView.setUpdatedTime(new Date());
        this.metadataViewMapper.updateByPrimaryKeySelective(updateMetadataView);
        this.metadataService.updateView(currMetadataView.getMetadataId(), userId);

        // 增加操作日志
        this.userOperationLogService.insert(UserOperationLog.builder()
                .userId(userId)
                .username(userMapper.selectByPrimaryKey(userId).getUsername())
                .type("MetadataView.Update")
                .content("更新视图: " + metadataView.getName())
                .params(metadataView.getId().toString())
                .createdTime(new Date())
                .build());

        return ApiResult.success(ViewItem.builder()
                .id(metadataView.getId())
                .name(metadataView.getName())
                .shortName(metadataView.getShortName())
                .build());
    }


    /**
     * 删除元数据视图
     *
     * @param id
     * @return
     */
    public ApiResult delete(Integer id, Integer userId) {
        MetadataView metadataView = this.metadataViewMapper.selectByPrimaryKey(id);
        if (metadataView == null) {
            return ApiResult.error("视图不存在");
        }
        this.metadataViewMapper.deleteByPrimaryKey(id);
        this.metadataEdgeMapper.deleteByViewId(id);
        this.metadataNodeMapper.deleteByViewId(id);
        this.metadataService.updateView(metadataView.getMetadataId(), userId);
        this.addDeleteOperationLog(metadataView, userId, true);
        return ApiResult.success();
    }

    /**
     * 清空视图
     *
     * @param id
     * @param metadataId
     * @return
     */
    public ApiResult clear(Integer id, Integer metadataId, Integer userId) {
        MetadataView metadataView = this.metadataViewMapper.selectByPrimaryKey(id);
        if (metadataView == null) {
            return ApiResult.error("视图不存在");
        }
        this.metadataEdgeMapper.deleteByViewId(id);
        this.metadataNodeMapper.deleteByViewId(id);
        this.metadataService.updateView(metadataId, userId);
        this.addDeleteOperationLog(metadataView, userId, false);
        return this.metadataService.getDetailByVewId(id);
    }

    @Autowired(required = false)
    UserOperationLogService userOperationLogService;
    @Autowired(required = false)
    UserMapper userMapper;

    /**
     * 添加删除操作日志
     *
     * @param metadataView
     * @param userId
     * @param isSelf
     */
    public void addDeleteOperationLog(MetadataView metadataView, Integer userId, Boolean isSelf) {
        User user = this.userMapper.selectByPrimaryKey(userId);
        if (user == null) {
            throw new IllegalArgumentException("用户不存在");
        }
        String actName=isSelf?"删除视图":"清空视图";
        List<Integer> nodeIds = this.metadataNodeMapper.getIdsByViewId(metadataView.getId());
        List<Integer> edgeIds = this.metadataEdgeMapper.getIdsByViewId(metadataView.getId());
        if (!nodeIds.isEmpty()) {
            this.userOperationLogService.insert(UserOperationLog.builder()
                    .userId(userId)
                    .username(user.getUsername())
                    .type("MetadataNode.Delete")
                    .content(actName+".联动删除关联的节点: " + nodeIds.size())
                    .params(String.join(",", nodeIds.stream().map(String::valueOf).collect(Collectors.toList())))
                    .createdTime(new Date())
                    .build());
        }
        if (!edgeIds.isEmpty()) {
            this.userOperationLogService.insert(UserOperationLog.builder()
                    .userId(userId)
                    .username(user.getUsername())
                    .type("MetadataEdge.Delete")
                    .content(actName+".联动删除关联的关系: " + edgeIds.size())
                    .params(String.join(",", edgeIds.stream().map(String::valueOf).collect(Collectors.toList())))
                    .createdTime(new Date())
                    .build());
        }
        if (isSelf) {
            this.userOperationLogService.insert(UserOperationLog.builder()
                    .userId(userId)
                    .username(user.getUsername())
                    .type("MetadataView.Delete")
                    .content(actName+": " + metadataView.getName())
                    .params(metadataView.getId().toString())
                    .createdTime(new Date())
                    .build());
        }
    }
}
